#include "forward_session_tcp.h"
#include "common.h"

#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>

forward_session_tcp::forward_session_tcp(forward_pair& fwd_pair) : forward_session(fwd_pair){
	reset();
}


forward_session_tcp::~forward_session_tcp(){

}

int forward_session_tcp::packet_forward(FORWARD_DIRECTION direction){

	int result = -1;

	int fd_src = direction ? fd_out : fd_in;
	int fd_dst = direction ? fd_in : fd_out;
	forward_buffer& fbuf = direction ? pend_buffer_out : pend_buffer_in;

	if (fd_src <= 0){
		return result;
	}
	if (fd_dst <= 0){
		return result;
	}

	char buffer[BUF_SIZ] = {0};

	result = 0;

	// 如果还有没发的报文，先不发了
	if (fbuf.get_data_len()>0){
		return result;
	}

	for(;;){
		bzero(buffer, sizeof(buffer));
		int recvlen = recv(fd_src, buffer, sizeof(buffer), 0);
		LOGI("recv %d ret %d, errno %d.", fd_src, recvlen, errno);
		if (recvlen == 0){
			LOGI("peer closed!");
			result = -1;
			break;
		}else if (recvlen == -1){
			if (errno == EAGAIN || errno == EWOULDBLOCK){
				// 暂无数据
				break;
			}else{
				// 接收异常，关闭会话
				LOGI("recv error!");
				result = -1;
				break;
			}
		}else{
			int ret = send(fd_dst, buffer, recvlen, 0);
			LOGI("send %d ret %d, errno %d.", fd_dst, ret, errno);
			if (ret == -1){
				if (errno == EAGAIN || errno == EWOULDBLOCK){
					LOGI("buffer is full!");
					fbuf.alloc();
					fbuf.write(buffer, recvlen);
					break;
				}else{
					// 发送异常，关闭会话
					LOGI("send error!");
					result = -1;
					break;
				}
			}else{
				if (ret != recvlen){
					LOGE("send incomplete!!!!! %d / %d", ret, recvlen);
					fbuf.alloc();
					fbuf.write(buffer+ret, recvlen-ret);
					break;
				}else{
					// 发送成功
					continue;
				}
			}
		}
	}

	return result;
}

int forward_session_tcp::pend_forward(FORWARD_DIRECTION direction){

	int result = 0;

	int fd_dst = direction ? fd_in : fd_out;
	forward_buffer& fbuf = direction ? pend_buffer_out : pend_buffer_in;

	int data_len = fbuf.get_data_len();
	if (data_len == 0){
		return result;
	}

	int ret = send(fd_dst, fbuf.get_data_ptr(), data_len, 0);
	LOGI("pend send %d ret %d, errno %d.", fd_dst, ret, errno);
	if (ret == -1){
		if (errno == EAGAIN || errno == EWOULDBLOCK){
			LOGI("pend buffer is full!");
			result = 1;
		}else{
			// 发送异常，关闭会话
			LOGI("pend send error!");
			result = -1;
		}
	}else{
		if (ret != data_len){
			LOGE("pend send incomplete!!!!! %d / %d", ret, data_len);
			result = 1;
			fbuf.erase_front(ret);
		}
		else{
			result = 2;
			// 完成了，释放
			fbuf.release();
		}
	}
	return result;
}

void forward_session_tcp::attach_fd_pair(int fd_in, int fd_out){
	this->fd_in = fd_in;
	this->fd_out = fd_out;
}

void forward_session_tcp::close(){
	if (fd_in >= 0){
		::close(fd_in);
	}
	if (fd_out >= 0){
		::close(fd_out);
	}
	forward_session::close();
}

void forward_session_tcp::reset(){
	status = CREATED;
	fd_in = -1;
	fd_out = -1;
	forward_session::reset();
}

const char* forward_session_tcp::to_string(){
	static char tmp [128] = {0};
	sprintf(tmp, "<session-%d %d,%d> status=%d", (int)(this), (int)fd_in, (int)fd_out, status);
	return tmp;
}



